package com.andong;

import java.util.*;

public class DBCompareMan {
	public static final String TABLE_CHANGED = "/* +TABLE_CHANGED+ %d */";
	public static final String VIEW_CHANGED = "/* +VIEW_CHANGED+ %d */";
	public static final String TABLE_CHANGED_END = "/* -TABLE_CHANGED_END- */";
	public static final String VIEW_CHANGED_END = "/* -VIEW_CHANGED_END- */";
	private DBReport firstDBReport;

	public DBCompareMan(DBReport firstDBReport, DBReport secondDBReport) {
		this.firstDBReport = firstDBReport;
		this.secondDBReport = secondDBReport;
	}

	private DBReport secondDBReport;

	public String compare() {
		if (this.firstDBReport.getDbTitle().isEmpty() || this.secondDBReport.getDbTitle().isEmpty()) {
			return "";
		}
		StringBuffer sbDBCompareResult = new StringBuffer();
		// 信息头
		sbDBCompareResult.append(this.firstDBReport.getDbTitle());
		if (this.firstDBReport.getTableTitle().isEmpty() || this.secondDBReport.getTableTitle().isEmpty()
			|| !this.firstDBReport.getTableTitle().equals(this.secondDBReport.getTableTitle())) {
			return sbDBCompareResult.toString();
		}
//		sbDbCpResult.append(this.firstDBReport.getTableTitle());
		if (this.firstDBReport.getTableReport().size() == 0
			|| this.firstDBReport.getTableReport().size() != this.secondDBReport.getTableReport().size()) {
			return sbDBCompareResult.toString();
		}
		StringBuffer tableChangedSb = getChangedResult(this.firstDBReport.getTableReport(),
			this.secondDBReport.getTableReport(), TABLE_CHANGED, TABLE_CHANGED_END);
		sbDBCompareResult.append(tableChangedSb + "\n");

		StringBuffer viewChangedSb = getChangedResult(this.firstDBReport.getViewReport(),
			this.secondDBReport.getViewReport(), VIEW_CHANGED, VIEW_CHANGED_END);
		sbDBCompareResult.append(viewChangedSb);

		return sbDBCompareResult.toString();
	}

	/**
	 * 根据报告明细, 生成对比结果
	 * @param firstDetailReport 第一个明细
	 * @param secondDetailReport 第二个明细
	 * @param title
	 * @param end
	 * @return
	 */
	private StringBuffer getChangedResult(TreeMap<String, Integer> firstDetailReport,
	                                      TreeMap<String, Integer> secondDetailReport,
	                                      String title, String end) {
		String tableChangedTitle;
		List<OneLineCompareResult> tableCompareResultList = compareTableReport(firstDetailReport,secondDetailReport);
		List<OneLineCompareResult> changedTableList = getChangedTableList(tableCompareResultList);

		StringBuffer tableChangedSb = new StringBuffer();
		tableChangedTitle = (title.isEmpty()) ? "" : String.format((title + "\n"), changedTableList.size());
		tableChangedSb.append(tableChangedTitle);
		if (changedTableList.size() > 0) {
			for (OneLineCompareResult tableChanged : changedTableList) {
				tableChangedSb.append(tableChanged.getTableName() + "\t"
					+ tableChanged.getFirstCount() + "\t" + tableChanged.getSecondCount() + "\t"
					+ (tableChanged.getSecondCount() - tableChanged.getFirstCount()) + "\n");
			}
		}
		if (!end.isEmpty()) {
			tableChangedSb.append(end);
		}
		return tableChangedSb;
	}

	private List<OneLineCompareResult> getChangedTableList(List<OneLineCompareResult> tableCompareResultList) {
		List<OneLineCompareResult> changedTableList = new ArrayList<>();
		for (OneLineCompareResult oneLineCompareResult : tableCompareResultList) {
			if (oneLineCompareResult.getFirstCount() != oneLineCompareResult.getSecondCount()) {
				// Write down changed table
				OneLineCompareResult tableChanged = new OneLineCompareResult();
				tableChanged.setTableName(oneLineCompareResult.getTableName());
				tableChanged.setFirstCount(oneLineCompareResult.getFirstCount());
				tableChanged.setSecondCount(oneLineCompareResult.getSecondCount());
				changedTableList.add(tableChanged);
			}
		}
		return changedTableList;
	}

	/**
	 * compare table report, return List(tablename, first count, second count)
	 * @param mapFirstReport  first table report
	 * @param mapSecondReport second table report
	 * @return compare result
	 */
	private static List<OneLineCompareResult> compareTableReport(TreeMap<String, Integer> mapFirstReport, TreeMap<String, Integer> mapSecondReport) {
		if (mapFirstReport.size() != mapSecondReport.size()) {
			return null;
		}
		Iterator<Map.Entry<String, Integer>> iterator = mapFirstReport.entrySet().iterator();
		List<OneLineCompareResult> compareResultArrayList = new ArrayList<>();
		while (iterator.hasNext()) {
			OneLineCompareResult oneLineCompareResult = new OneLineCompareResult();
			Map.Entry<String, Integer> entry = iterator.next();
			oneLineCompareResult.setTableName(entry.getKey());
			oneLineCompareResult.setFirstCount(entry.getValue());
			oneLineCompareResult.setSecondCount(mapSecondReport.get(entry.getKey()));
			compareResultArrayList.add(oneLineCompareResult);
		}
		return compareResultArrayList;
	}
}
